﻿using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.Practices.Unity;

namespace TSharp.Core.Asm
{
    /// <summary>
    /// 服务注册异常
    /// <para>2010/12/24</para>
    /// 	<para>THINKPADT61</para>
    /// 	<para>tangjingbo</para>
    /// </summary>
    public class ServiceException : Exception
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ServiceException"/> class.
        /// </summary>
        /// <param name="arg0">The arg0.</param>
        public ServiceException(String arg0)
            : base(arg0)
        {
        }
    }

    /// <summary>
    /// 服务注册管理
    /// <para>2010/12/24</para>
    /// 	<para>THINKPADT61</para>
    /// 	<para>tangjingbo</para>
    /// </summary>
    internal class ServiceManager : ExtensionPoint<ServiceAttribute>
    {
        private static readonly ServiceInfoList rootMap = new ServiceInfoList();
        private static readonly ServiceInfoList sessionMap = new ServiceInfoList();
        private static readonly ServiceInfoList requsetMap = new ServiceInfoList();

        internal static ServiceInfoList RootMap
        {
            get { return rootMap; }
        }

        internal static ServiceInfoList SessionMap
        {
            get { return sessionMap; }
        }

        internal static ServiceInfoList RequsetMap
        {
            get { return requsetMap; }
        }

        /// <summary>
        /// 注册后期绑定关系
        /// </summary>
        internal static void RegisterService(ServiceAttribute attribute)
        {
            switch (attribute.Level)
            {
                case Level.REQUSET:
                    requsetMap.Add(attribute);
                    break;
                case Level.SESSION:
                    sessionMap.Add(attribute);
                    break;
                case Level.ROOT:
                    rootMap.Add(attribute);
                    break;
                default:
                    throw new ServiceException("无效的容器类型。");
            }
        }

        /// <summary>
        /// 注销后期绑定关系，如果该类型被多次注册，将移除优先级最低的
        /// </summary>
        public static void UnRegisterService(ServiceAttribute attribute)
        {
            switch (attribute.Level)
            {
                case Level.REQUSET:
                    requsetMap.Remove(attribute);
                    break;
                case Level.SESSION:
                    sessionMap.Remove(attribute);
                    break;
                case Level.ROOT:
                    rootMap.Remove(attribute);
                    break;
                default:
                    throw new ServiceException("无效的容器类型。");
            }
        }

        #region IExtensionPoint 成员

        /// <summary>
        /// Registers the specified assembly.
        /// </summary>
        /// <param name="assembly">The assembly.</param>
        /// <param name="attribute">The attribute.</param>
        public override void Register(Assembly assembly, ServiceAttribute attribute)
        {
            RegisterService(attribute);
        }

        /// <summary>
        /// Uns the register.
        /// </summary>
        /// <param name="assembly">The assembly.</param>
        /// <param name="attribute">The attribute.</param>
        public override void UnRegister(Assembly assembly, ServiceAttribute attribute)
        {
            UnRegisterService(attribute);
        }

        #endregion
    }

    internal class ServiceInfoList
    {
        private readonly List<ServiceAttribute> _list = new List<ServiceAttribute>(0xff);

        public void Add(ServiceAttribute attribute)
        {
            _list.Add(attribute);
        }
        public bool Remove(ServiceAttribute attribute)
        {
            return _list.Remove(attribute);
        }
        private void Sort()
        {
            if (_list.Count > 1)
            {
                _list.Sort((a, b) =>
                               {
                                   if (a.IntfType != null && a.IntfType.Equals(b.IntfType))
                                       return a.Priority - b.Priority;
                                   return 0;
                               });
            }
        }

        public void Configure(IUnityContainer unityContainer)
        {
            Sort();
            foreach (ServiceAttribute lb in _list)
            {
                if (lb.IntfType != null)
                    unityContainer.RegisterType(lb.IntfType, lb.ImplType, lb.Name,
                                                new ContainerControlledLifetimeManager());
                else if (lb.ImplType != null)
                    unityContainer.RegisterType(lb.ImplType, lb.Name, new ContainerControlledLifetimeManager());
            }
        }
    }
}